<?php

namespace MathPHP\Tests\Functions\Special;

use MathPHP\Functions\Special;
use MathPHP\Exception;

class HypergeometricTest extends \PHPUnit\Framework\TestCase
{
    /**
     * @test         confluentHypergeometric returns the expected value
     * @dataProvider dataProviderForConfluentHypergeometric
     * @param        float $a
     * @param        float $b
     * @param        float $z
     * @param        float $expected
     * @throws       \Exception
     */
    public function testConfluentHypergeometric(float $a, float $b, float $z, float $expected)
    {
        // When
        $actual = Special::confluentHypergeometric($a, $b, $z);

        // Then
        $this->assertEqualsWithDelta($expected, $actual, \abs($expected) * 1e-7 + 1e-12);
    }

    /**
     * Comprehensive test data from SciPy scipy.special.hyp1f1
     * Source: NIST DLMF §13.2 (Confluent Hypergeometric Function)
     * https://dlmf.nist.gov/13.2
     * @return array
     */
    public function dataProviderForConfluentHypergeometric(): array
    {
        return [
            [6.464756838, 0.509199496, 0.241379523, 6.4811484506047154],
            [5.12297443791641, 5.26188297019653, 0.757399855727661, 2.09281409217445],
            [9.89309990528122, 6.92782493869175, 0.71686043176351, 2.7336625501433436],
            [8.59824618495037, 6.66955518297157, 0.0293511981644408, 1.0385422694416306],
            [1, 1, 0.5, 1.6487212707001282],
            [1, 2, 0.5, 1.2974425414002564],
            [2, 3, 0.5, 1.4051149171994872],
            [0.5, 1.5, 0.5, 1.1949576619102276],
            [1, 1, 1.0, 2.7182818284590451],
            [2, 3, 1.0, 1.9999999999999996],
            [3, 5, 1.0, 1.8581458245256288],
            [1, 2, 2.0, 3.1945280494653252],
            [2, 3, 2.0, 4.1945280494653234],
            [3, 4, 2.0, 4.7917920741979874],
            [1.5, 2.5, 2.0, 3.7684516545940796],
            [0.5, 1.5, 3.0, 4.2222119928885116],
            [1, 3, 3.0, 3.5745637607083705],
            [2, 4, 3.0, 5.5745637607083696],
            [1, 2, 5.0, 2.94826318205153193e+01],
            [2, 4, 5.0, 2.17074949107710360e+01],
            [0.5, 2.5, 5.0, 6.0720864614519643],
            [1.5, 3.5, 5.0, 1.66501069685842751e+01],
            [0.25, 0.75, 1.0, 1.4933621510668700],
            [0.75, 1.25, 1.5, 2.7462521399613080],
            [1.25, 2.25, 2.0, 3.5048035047485873],
            [0.3, 0.9, 1.2, 1.6329050578184541],
            [0.7, 1.7, 1.8, 2.4358573658039999],
            [1, 1, 0.1, 1.1051709180756477],
            [1, 1, 0.01, 1.0100501670841679],
            [2, 2, 1.0, 2.7182818284590451],
            [3, 3, 1.0, 2.7182818284590451],
            [1, 5, 2.0, 1.5835841483959756],
            [2, 7, 3.0, 2.6705443492589280],
            [0.5, 4.5, 2.5, 1.4147437529983273],
            [0.5, 1.5, 1.0, 1.4626517459071813],
            [1, 1, 2.0, 7.3890560989306504],
            [1.2, 2.3, 0.8, 1.5548051130184906],
            [2.5, 3.7, 1.5, 2.8938157084787237],
            [0.8, 1.9, 2.2, 3.1058221605674725],
            [3.2, 4.1, 1.3, 2.8315701485738223],
            [0.6, 2.4, 3.1, 2.9898441929061739],
            [1.8, 3.6, 0.9, 1.6030979254875257],
            [2.2, 4.5, 2.7, 4.4064323386061597],
            [0.4, 1.2, 1.7, 2.0651908584961336],
            [1.6, 2.8, 2.3, 4.3627856762890245],
            [3.5, 5.2, 1.1, 2.1405759272517084],
        ];
    }

    /**
     * @test         hypergeometric returns the expected value
     * @dataProvider dataProviderForHypergeometric
     * @param        float $a
     * @param        float $b
     * @param        float $c
     * @param        float $z
     * @param        float $expected
     * @throws       \Exception
     */
    public function testHypergeometric(float $a, float $b, float $c, float $z, float $expected)
    {
        // When
        $actual = Special::hypergeometric($a, $b, $c, $z);

        // Then
        $this->assertEqualsWithDelta($expected, $actual, \abs($expected) * 1e-6 + 1e-12);
    }

    /**
     * Comprehensive test data from SciPy scipy.special.hyp2f1
     * Source: NIST DLMF §15.2 (Gauss Hypergeometric Function)
     * https://dlmf.nist.gov/15.2
     * @return array
     */
    public function dataProviderForHypergeometric(): array
    {
        return [
            [1, 1, 1, .9, 10],
            [1, 1, 1, .8, 5],
            [1, 1, 1, .7, 3.333333333333333],
            [3, 1.4, 1.5, .926, 1746.2063659363855],
            [1, 1, 1, 0.1, 1.1111111111111112],
            [1, 1, 1, 0.2, 1.2500000000000000],
            [1, 1, 1, 0.5, 2.0000000000000000],
            [1, 1, 2, 0.5, 1.3862943611198901],
            [1, 2, 3, 0.5, 1.5451774444795621],
            [2, 3, 4, 0.5, 2.7289353331226236],
            [0.5, 0.5, 1.5, 0.5, 1.1107207345395911],
            [0.5, 1.5, 2.5, 0.5, 1.2108418600591315],
            [1.5, 2.5, 3.5, 0.5, 2.0337170231396291],
            [1, 2, 2, 0.5, 2.0000000000000000],
            [2, 3, 5, 0.5, 2.1685173350190006],
            [1, 1, 2, 0.8, 2.0117973905426241],
            [1, 2, 3, 0.8, 2.5294934763565631],
            [0.5, 0.5, 1, 0.8, 1.4369815413475839],
            [0.5, 1, 2, 0.9, 1.5194938532959135],
            [1, 1, 3, 0.9, 1.6536826930878890],
            [0.25, 0.75, 1.25, 0.4, 1.0758654542944417],
            [0.3, 0.7, 1.3, 0.6, 1.1438964323298977],
            [0.6, 1.2, 2.1, 0.5, 1.2467367558630080],
            [1.4, 2.3, 3.2, 0.4, 1.6456753307577194],
            [1, 1, 1, 0.01, 1.0101010101010102],
            [2, 2, 3, 0.05, 1.0706276478543100],
            [1, 2, 2, 0.1, 1.1111111111111112],
            [0.5, 1.5, 2, 0.15, 1.0621780221678141],
            [0.5, 0.5, 1, 0.5, 1.1803405990160953],
            [0.5, 1, 1.5, 0.5, 1.2464504802804612],
            [0.8, 1.3, 2.1, 0.3, 1.1871970923173989],
            [1.2, 1.8, 2.6, 0.4, 1.5089388006287558],
            [0.4, 0.9, 1.7, 0.6, 1.1900251944780691],
            [1.6, 2.4, 3.5, 0.35, 1.5826653750675759],
            [0.7, 1.5, 2.3, 0.55, 1.4045816879560769],
            [1.3, 2.1, 3.1, 0.45, 1.6555386224929904],
            [0.9, 1.7, 2.8, 0.5, 1.4230994855462737],
            [1.1, 1.9, 2.9, 0.4, 1.4234880211758474],
            [0.6, 1.4, 2.2, 0.65, 1.4364343292485564],
            [1.5, 2.5, 3.7, 0.3, 1.4214419569129735],
            [0.5, 0.5, 1, 0.95, 1.8515049970729258],
            [2, 1, 3, 0.75, 2.2623799506485018],
            [1, 3, 4, 0.7, 2.2650682594105205],
            [3, 2, 5, 0.6, 2.7151219790258452],
            [1, 1, 2, -0.5, 0.8109302162163285]
        ];
    }

    /**
     * @test         hypergeometric with negative z returns the expected value
     * @dataProvider dataProviderForHypergeometricNegativeZ
     * @param        float $a
     * @param        float $b
     * @param        float $c
     * @param        float $z
     * @param        float $expected
     * @throws       \Exception
     */
    public function testHypergeometricNegativeZ(float $a, float $b, float $c, float $z, float $expected)
    {
        // When
        $actual = Special::hypergeometric($a, $b, $c, $z);

        // Then
        $this->assertEqualsWithDelta($expected, $actual, \abs($expected) * 1e-6 + 1e-12);
    }

    /**
     * Test data for hypergeometric function with negative z values
     * Generated using SciPy scipy.special.hyp2f1
     * Source: NIST DLMF §15.2 (Gauss Hypergeometric Function)
     * https://dlmf.nist.gov/15.2
     * @return array
     */
    public function dataProviderForHypergeometricNegativeZ(): array
    {
        return [
            // [a, b, c, z, expected]
            [1, 1, 2, -0.1, 0.9531017980432486],
            [1, 1, 2, -0.3, 0.8745475482249703],
            [1, 1, 2, -0.5, 0.8109302162163285],
            [1, 1, 2, -0.7, 0.7580403586602431],
            [1, 1, 2, -0.9, 0.7131709846359938],
            [1, 1, 3, -0.1, 0.9682395569514693],
            [1, 1, 3, -0.3, 0.9127454179497416],
            [1, 1, 3, -0.5, 0.8655812972979726],
            [1, 1, 3, -0.7, 0.8247674563497538],
            [1, 1, 3, -0.9, 0.7889441573519750],
            [1, 1, 4, -0.1, 0.9759526896992421],
            [1, 1, 4, -0.3, 0.9328452166733198],
            [1, 1, 4, -0.5, 0.8951158378408767],
            [1, 1, 4, -0.7, 0.8616528767026747],
            [1, 1, 4, -0.9, 0.8316564982812555],
            [1, 1, 5, -0.1, 0.9806394489222157],
            [1, 1, 5, -0.3, 0.9453279185569586],
            [1, 1, 5, -0.5, 0.9137966846968397],
            [1, 1, 5, -0.7, 0.8853521721800887],
            [1, 1, 5, -0.9, 0.8594775507176088],
            [1, 2, 3, -0.1, 0.9379640391350281],
            [1, 2, 3, -0.3, 0.8363496785001989],
            [1, 2, 3, -0.5, 0.7562791351346845],
            [1, 2, 3, -0.7, 0.6913132609707331],
            [1, 2, 3, -0.9, 0.6373978119200129],
            [1, 2, 4, -0.1, 0.9528132914559237],
            [1, 2, 4, -0.3, 0.8725458205025853],
            [1, 2, 4, -0.5, 0.8065122162121645],
            [1, 2, 4, -0.7, 0.7509966156439122],
            [1, 2, 4, -0.9, 0.7035194754934149],
            [1, 2, 5, -0.1, 0.9618924120303215],
            [1, 2, 5, -0.3, 0.8953971110224030],
            [1, 2, 5, -0.5, 0.8390732972729869],
            [1, 2, 5, -0.7, 0.7905549902704320],
            [1, 2, 5, -0.9, 0.7481933409721969],
            [1, 3, 4, -0.1, 0.9305394129745801],
            [1, 3, 4, -0.3, 0.8182516074990058],
            [1, 3, 4, -0.5, 0.7311625945959457],
            [1, 3, 4, -0.7, 0.6614715836341432],
            [1, 3, 4, -0.9, 0.6043369801333115],
            [1, 3, 5, -0.1, 0.9437341708815258],
            [1, 3, 5, -0.3, 0.8496945299827673],
            [1, 3, 5, -0.5, 0.7739511351513418],
            [1, 3, 5, -0.7, 0.7114382410173932],
            [1, 3, 5, -0.9, 0.6588456100146333],
            [2, 1, 3, -0.1, 0.9379640391350281],
            [2, 1, 3, -0.3, 0.8363496785001989],
            [2, 1, 3, -0.5, 0.7562791351346845],
            [2, 1, 3, -0.7, 0.6913132609707331],
            [2, 1, 3, -0.9, 0.6373978119200129],
            [2, 1, 4, -0.1, 0.9528132914559237],
            [2, 1, 4, -0.3, 0.8725458205025853],
            [2, 1, 4, -0.5, 0.8065122162121645],
            [2, 1, 4, -0.7, 0.7509966156439122],
            [2, 1, 4, -0.9, 0.7035194754934149],
            [2, 1, 5, -0.1, 0.9618924120303215],
            [2, 1, 5, -0.3, 0.8953971110224030],
            [2, 1, 5, -0.5, 0.8390732972729869],
            [2, 1, 5, -0.7, 0.7905549902704320],
            [2, 1, 5, -0.9, 0.7481933409721969],
            [2, 2, 3, -0.1, 0.8802177790467903],
            [2, 2, 3, -0.3, 0.7021118599613396],
            [2, 2, 3, -0.5, 0.5770541981986483],
            [2, 2, 3, -0.7, 0.4851573272645611],
            [2, 2, 3, -0.9, 0.4152337670273552],
            [2, 2, 4, -0.1, 0.9082655344932368],
            [2, 2, 4, -0.3, 0.7639573944954267],
            [2, 2, 4, -0.5, 0.6558129729797260],
            [2, 2, 4, -0.7, 0.5719465516243744],
            [2, 2, 4, -0.9, 0.5051544847732088],
            [2, 2, 5, -0.1, 0.9255759297327300],
            [2, 2, 5, -0.3, 0.8039919489431306],
            [2, 2, 5, -0.5, 0.7088289730296969],
            [2, 2, 5, -0.7, 0.6323214917643545],
            [2, 2, 5, -0.9, 0.5694978790570696],
            [2, 3, 4, -0.1, 0.8661939013235670],
            [2, 3, 4, -0.3, 0.6711890926942964],
            [2, 3, 4, -0.5, 0.5376748108081096],
            [2, 3, 4, -0.7, 0.4417627150846543],
            [2, 3, 4, -0.9, 0.3702734081544289],
            [2, 3, 5, -0.1, 0.8909551392537431],
            [2, 3, 5, -0.3, 0.7239228400477223],
            [2, 3, 5, -0.5, 0.6027969729297548],
            [2, 3, 5, -0.7, 0.5115716114843945],
            [2, 3, 5, -0.9, 0.4408110904893477],
            [3, 1, 4, -0.1, 0.9305394129745801],
            [3, 1, 4, -0.3, 0.8182516074990058],
            [3, 1, 4, -0.5, 0.7311625945959457],
            [3, 1, 4, -0.7, 0.6614715836341432],
            [3, 1, 4, -0.9, 0.6043369801333115],
            [3, 1, 5, -0.1, 0.9437341708815258],
            [3, 1, 5, -0.3, 0.8496945299827673],
            [3, 1, 5, -0.5, 0.7739511351513418],
            [3, 1, 5, -0.7, 0.7114382410173932],
            [3, 1, 5, -0.9, 0.6588456100146333],
            [3, 2, 4, -0.1, 0.8661939013235670],
            [3, 2, 4, -0.3, 0.6711890926942964],
            [3, 2, 4, -0.5, 0.5376748108081096],
            [3, 2, 4, -0.7, 0.4417627150846543],
            [3, 2, 4, -0.9, 0.3702734081544289],
            [3, 2, 5, -0.1, 0.8909551392537431],
            [3, 2, 5, -0.3, 0.7239228400477223],
            [3, 2, 5, -0.5, 0.6027969729297548],
            [3, 2, 5, -0.7, 0.5115716114843945],
            [3, 2, 5, -0.9, 0.4408110904893477],
            [3, 3, 4, -0.1, 0.8065724708258198],
            [3, 3, 4, -0.3, 0.5519794181498933],
            [3, 3, 4, -0.5, 0.3978292612626118],
            [3, 3, 4, -0.7, 0.2981497843261851],
            [3, 3, 4, -0.9, 0.2303757612967467],
            [3, 3, 5, -0.1, 0.8414326633933908],
            [3, 3, 5, -0.3, 0.6184553453408697],
            [3, 3, 5, -0.5, 0.4725526486864646],
            [3, 3, 5, -0.7, 0.3719538186849144],
            [3, 3, 5, -0.9, 0.2997357258195103],
            [0.5, 0.5, 1.5, -0.05, 0.9918487694660366],
            [0.5, 0.5, 1.5, -0.15, 0.9765506887574015],
            [0.5, 0.5, 1.5, -0.25, 0.9624236501192069],
            [0.5, 0.5, 1.5, -0.4, 0.9430787387986125],
            [0.5, 0.5, 1.5, -0.6, 0.9201026803190610],
            [0.5, 0.5, 1.5, -0.8, 0.8997031444420005],
            [0.5, 0.5, 1.5, -0.95, 0.8857839842196527],
            [0.5, 1.5, 2.5, -0.05, 0.9853892138976930],
            [0.5, 1.5, 2.5, -0.15, 0.9582984071895947],
            [0.5, 1.5, 2.5, -0.25, 0.9336620317841279],
            [0.5, 1.5, 2.5, -0.4, 0.9005145668299149],
            [0.5, 1.5, 2.5, -0.6, 0.8620209593707264],
            [0.5, 1.5, 2.5, -0.8, 0.8286330788585125],
            [0.5, 1.5, 2.5, -0.95, 0.8062737160377506],
            [1.5, 2.5, 3.5, -0.05, 0.9489140949159677],
            [1.5, 2.5, 3.5, -0.15, 0.8597866316427043],
            [1.5, 2.5, 3.5, -0.25, 0.7846968156842370],
            [1.5, 2.5, 3.5, -0.4, 0.6920039012674823],
            [1.5, 2.5, 3.5, -0.6, 0.5954295360719257],
            [1.5, 2.5, 3.5, -0.8, 0.5204817897411400],
            [1.5, 2.5, 3.5, -0.95, 0.4745202210437748],
            [0.25, 0.75, 1.25, -0.05, 0.9926767070872659],
            [0.25, 0.75, 1.25, -0.15, 0.9789995153554143],
            [0.25, 0.75, 1.25, -0.25, 0.9664430869993256],
            [0.25, 0.75, 1.25, -0.4, 0.9493563730913566],
            [0.25, 0.75, 1.25, -0.6, 0.9292114979552468],
            [0.25, 0.75, 1.25, -0.8, 0.9114495945077756],
            [0.25, 0.75, 1.25, -0.95, 0.8993915661930546],
            [0.3, 0.7, 1.3, -0.05, 0.9921112215050470],
            [0.3, 0.7, 1.3, -0.15, 0.9773668326478413],
            [0.3, 0.7, 1.3, -0.25, 0.9638187960650970],
            [0.3, 0.7, 1.3, -0.4, 0.9453661375462321],
            [0.3, 0.7, 1.3, -0.6, 0.9235891307614963],
            [0.3, 0.7, 1.3, -0.8, 0.9043714630267663],
            [0.3, 0.7, 1.3, -0.95, 0.8913175922957547],
            [0.6, 1.2, 2.1, -0.05, 0.9833279071739881],
            [0.6, 1.2, 2.1, -0.15, 0.9525509945683778],
            [0.6, 1.2, 2.1, -0.25, 0.9247133572524459],
            [0.6, 1.2, 2.1, -0.4, 0.8874812421712567],
            [0.6, 1.2, 2.1, -0.6, 0.8445585349566983],
            [0.6, 1.2, 2.1, -0.8, 0.8075976461634119],
            [0.6, 1.2, 2.1, -0.95, 0.7829830980740062],
            [1.4, 2.3, 3.2, -0.05, 0.9519532211960781],
            [1.4, 2.3, 3.2, -0.15, 0.8677792445951462],
            [1.4, 2.3, 3.2, -0.25, 0.7964837301108675],
            [1.4, 2.3, 3.2, -0.4, 0.7079328112776266],
            [1.4, 2.3, 3.2, -0.6, 0.6149384614032982],
            [1.4, 2.3, 3.2, -0.8, 0.5421614090949004],
            [1.4, 2.3, 3.2, -0.95, 0.4972262735148426],
            [0.8, 1.3, 2.1, -0.05, 0.9760349645306911],
            [0.8, 1.3, 2.1, -0.15, 0.9324059798410189],
            [0.8, 1.3, 2.1, -0.25, 0.8936208088872442],
            [0.8, 1.3, 2.1, -0.4, 0.8427431029204541],
            [0.8, 1.3, 2.1, -0.6, 0.7854922785384850],
            [0.8, 1.3, 2.1, -0.8, 0.7373886509203319],
            [0.8, 1.3, 2.1, -0.95, 0.7059640270176100],
            [1.2, 1.8, 2.6, -0.05, 0.9601635429789546],
            [1.2, 1.8, 2.6, -0.15, 0.8895141554097136],
            [1.2, 1.8, 2.6, -0.25, 0.8287378861152099],
            [1.2, 1.8, 2.6, -0.4, 0.7519083904012637],
            [1.2, 1.8, 2.6, -0.6, 0.6693886556104187],
            [1.2, 1.8, 2.6, -0.8, 0.6032824013404309],
            [1.2, 1.8, 2.6, -0.95, 0.5616955270766840],
            [1, 1, 2, -0.001, 0.9995003330835331],
            [1, 2, 3, -0.001, 0.9993338329336662],
            [2, 3, 4, -0.001, 0.9985017980021408],
            [0.5, 0.5, 1, -0.001, 0.9997501405274184],
            [1, 1, 2, -0.01, 0.9950330853168083],
            [1, 2, 3, -0.01, 0.9933829366383430],
            [2, 3, 4, -0.01, 0.9851780212058810],
            [0.5, 0.5, 1, -0.01, 0.9975139655854249],
            [1, 1, 2, -0.05, 0.9758032833886400],
            [1, 2, 3, -0.05, 0.9678686644543975],
            [2, 3, 4, -0.05, 0.9292627244067099],
            [0.5, 0.5, 1, -0.05, 0.9878398046058009],
            [1, 1, 3, -0.99, 0.7741820856758247],
            [1, 2, 4, -0.99, 0.6842967100732573],
            [0.5, 0.5, 2, -0.99, 0.9072141160340338],
            [0.5, 1, 2, -0.99, 0.8296436322557346],
            [1, 1, 3, -0.95, 0.7806477042050481],
            [1, 2, 4, -0.95, 0.6926914604051102],
            [0.5, 0.5, 2, -0.95, 0.9101258444577605],
            [0.5, 1, 2, -0.95, 0.8345768513197772],
            [1, 1, 3, -0.9, 0.7889441573519750],
            [1, 2, 4, -0.9, 0.7035194754934149],
            [0.5, 0.5, 2, -0.9, 0.9138371538874374],
            [0.5, 1, 2, -0.9, 0.8408997226867161],
            [1, 1, 3, -0.85, 0.7974904700814721],
            [1, 2, 4, -0.85, 0.7147395173595095],
            [0.5, 0.5, 2, -0.85, 0.9176313859311723],
            [0.5, 1, 2, -0.85, 0.8474048255848101],
            [0.4, 0.9, 1.7, -0.2, 0.9613605146732903],
            [0.4, 0.9, 1.7, -0.35, 0.9364049901795143],
            [0.4, 0.9, 1.7, -0.5, 0.9141201276663468],
            [0.4, 0.9, 1.7, -0.65, 0.8940142456620072],
            [0.4, 0.9, 1.7, -0.8, 0.8757193127619889],
            [1.6, 2.4, 3.5, -0.2, 0.8167283875903476],
            [1.6, 2.4, 3.5, -0.35, 0.7147704655929022],
            [1.6, 2.4, 3.5, -0.5, 0.6333284980460995],
            [1.6, 2.4, 3.5, -0.65, 0.5669044302118895],
            [1.6, 2.4, 3.5, -0.8, 0.5117905697984968],
            [0.7, 1.5, 2.3, -0.2, 0.9189643364217913],
            [0.7, 1.5, 2.3, -0.35, 0.8689706864577333],
            [0.7, 1.5, 2.3, -0.5, 0.8258294142351544],
            [0.7, 1.5, 2.3, -0.65, 0.7880916432196782],
            [0.7, 1.5, 2.3, -0.8, 0.7547081396541245],
            [1.3, 2.1, 3.1, -0.2, 0.8499069982950875],
            [1.3, 2.1, 3.1, -0.35, 0.7634734940644443],
            [1.3, 2.1, 3.1, -0.5, 0.6926319754695063],
            [1.3, 2.1, 3.1, -0.65, 0.6334903137226762],
            [1.3, 2.1, 3.1, -0.8, 0.5833607011203754],
            [0.9, 1.7, 2.8, -0.2, 0.9035677426146564],
            [0.9, 1.7, 2.8, -0.35, 0.8446837900773799],
            [0.9, 1.7, 2.8, -0.5, 0.7942856356588939],
            [0.9, 1.7, 2.8, -0.65, 0.7505413715455378],
            [0.9, 1.7, 2.8, -0.8, 0.7121294308829372],
            [1.1, 1.9, 2.9, -0.2, 0.8752044055441981],
            [1.1, 1.9, 2.9, -0.35, 0.8013804118542831],
            [1.1, 1.9, 2.9, -0.5, 0.7396559529943033],
            [1.1, 1.9, 2.9, -0.65, 0.6871921584150588],
            [1.1, 1.9, 2.9, -0.8, 0.6419902178422259],
            [0.6, 1.4, 2.2, -0.2, 0.9316830890097372],
            [0.6, 1.4, 2.2, -0.35, 0.8889731086513285],
            [0.6, 1.4, 2.2, -0.5, 0.8517513478837102],
            [0.6, 1.4, 2.2, -0.65, 0.8189004125865592],
            [0.6, 1.4, 2.2, -0.8, 0.7896032263974367],
            [1.5, 2.5, 3.7, -0.2, 0.8291659316384057],
            [1.5, 2.5, 3.7, -0.35, 0.7326759363956804],
            [1.5, 2.5, 3.7, -0.5, 0.6547545012851045],
            [1.5, 2.5, 3.7, -0.65, 0.5905848895887553],
            [1.5, 2.5, 3.7, -0.8, 0.5368794576111846],
            [2.5, 3.5, 4.5, -0.2, 0.6996806851164189],
            [2.5, 3.5, 4.5, -0.35, 0.5539762668758167],
            [2.5, 3.5, 4.5, -0.5, 0.4487163097070662],
            [2.5, 3.5, 4.5, -0.65, 0.3702780659993595],
            [2.5, 3.5, 4.5, -0.8, 0.3103191211201045],
            [3.5, 4.5, 5.5, -0.2, 0.5916828587022882],
            [3.5, 4.5, 5.5, -0.35, 0.4203422379042139],
            [3.5, 4.5, 5.5, -0.5, 0.3089841854610766],
            [3.5, 4.5, 5.5, -0.65, 0.2335238047264928],
            [3.5, 4.5, 5.5, -0.8, 0.1806096943952838],
            [0, 1, 1, -0.1, 1.0000000000000000],
            [1, 0, 1, -0.1, 1.0000000000000000],
            [0, 1, 2, -0.1, 1.0000000000000000],
            [1, 0, 2, -0.1, 1.0000000000000000],
            [0, 1, 3, -0.1, 1.0000000000000000],
            [1, 0, 3, -0.1, 1.0000000000000000],
            [0, 1, 1, -0.5, 1.0000000000000000],
            [1, 0, 1, -0.5, 1.0000000000000000],
            [0, 1, 2, -0.5, 1.0000000000000000],
            [1, 0, 2, -0.5, 1.0000000000000000],
            [0, 1, 3, -0.5, 1.0000000000000000],
            [1, 0, 3, -0.5, 1.0000000000000000],
            [0, 1, 1, -0.9, 1.0000000000000000],
            [1, 0, 1, -0.9, 1.0000000000000000],
            [0, 1, 2, -0.9, 1.0000000000000000],
            [1, 0, 2, -0.9, 1.0000000000000000],
            [0, 1, 3, -0.9, 1.0000000000000000],
            [1, 0, 3, -0.9, 1.0000000000000000],
            [1, 1, 1, -0.1, 0.9090909090909091],
            [2, 1, 2, -0.1, 0.9090909090909091],
            [2.5, 1, 2.5, -0.1, 0.9090909090909091],
            [1, 1, 1, -0.3, 0.7692307692307692],
            [2, 1, 2, -0.3, 0.7692307692307692],
            [2.5, 1, 2.5, -0.3, 0.7692307692307692],
            [1, 1, 1, -0.5, 0.6666666666666666],
            [2, 1, 2, -0.5, 0.6666666666666666],
            [2.5, 1, 2.5, -0.5, 0.6666666666666666],
            [1, 1, 1, -0.7, 0.5882352941176471],
            [2, 1, 2, -0.7, 0.5882352941176471],
            [2.5, 1, 2.5, -0.7, 0.5882352941176471],
            [5, 6, 7, -0.1, 0.6641996032868583],
            [5, 6, 7, -0.2, 0.4565954263615560],
            [5, 6, 7, -0.4, 0.2343583417017625],
            [5, 6, 7, -0.6, 0.1311022926404619],
            [4, 5, 6, -0.1, 0.7272934289175277],
            [4, 5, 6, -0.2, 0.5431324766012938],
            [4, 5, 6, -0.4, 0.3228037627017557],
            [4, 5, 6, -0.6, 0.2050288076811847],
            [3, 4, 8, -0.1, 0.8651454977491461],
            [3, 4, 8, -0.2, 0.7554777410211982],
            [3, 4, 8, -0.4, 0.5896275414218390],
            [3, 4, 8, -0.6, 0.4719360067057624],
            [2.5, 3.5, 5.5, -0.1, 0.8582655303036539],
            [2.5, 3.5, 5.5, -0.2, 0.7449126959190999],
            [2.5, 3.5, 5.5, -0.4, 0.5767415029807611],
            [2.5, 3.5, 5.5, -0.6, 0.4597522254896537],
            [4.5, 5.5, 7.5, -0.1, 0.7291050850205130],
            [4.5, 5.5, 7.5, -0.2, 0.5450684282604032],
            [4.5, 5.5, 7.5, -0.4, 0.3236617383391239],
            [4.5, 5.5, 7.5, -0.6, 0.2048241655433488],
            [1.9352465823520764, 4.75850010140859, 7.088484955937102, -0.3872610248547856, 0.6442897281620216],
            [0.864491338167939, 0.864373149647393, 1.5097003685884378, -0.13579442297156094, 0.9385063784344827],
            [3.0454635575417233, 3.569555631200623, 4.1210168669401295, -0.03828473896772534, 0.9055981181258921],
            [4.178968939922067, 1.1404616423235532, 5.133531357939818, -0.7775997607377721, 0.5759669999014081],
            [1.5907869905017349, 2.6713065149979656, 4.251169061603255, -0.6762446082138406, 0.5820521143541894],
            [3.0980791841396598, 0.783519917195005, 4.3284408054777055, -0.6056198673039298, 0.7580182338975152],
            [2.334742922663476, 3.947362210825767, 4.946546666221667, -0.4666196278912051, 0.4840520523626055],
            [3.0028313874240085, 0.3276070223279889, 5.021693517177604, -0.7897073237339459, 0.8832837069078793],
            [0.41875280562786965, 4.749539132541333, 7.663619215227731, -0.19010649277052652, 0.9546554587322530],
            [1.5926074689495164, 0.578593358631281, 3.803190035229909, -0.5362566558847748, 0.8933225285753449],
            [0.6979873507394163, 2.526366859545224, 3.11233816233327, -0.09523882204594486, 0.9495185956514808],
            [1.368021909840083, 3.346359193334512, 4.625636883558039, -0.4611360600928578, 0.6794364157368796],
            [2.7788803687820707, 1.0057868320750825, 5.702841938193467, -0.2213751460405523, 0.9034538164443215],
            [4.703544813664527, 4.48465401709548, 6.69829476069224, -0.08343821907827019, 0.7762833196090718],
            [0.5336132600544056, 1.0603160258538116, 1.6733842481301568, -0.6441894890825315, 0.8397975520099182],
            [2.004518719478462, 1.42961025569209, 4.576362492358285, -0.614651872908026, 0.7240688085324501],
            [1.4765790974681658, 2.7592108074754176, 3.611521369912324, -0.1959348380912027, 0.8156128068249100],
            [0.46529815403087704, 4.935745989342535, 7.366357912584179, -0.7632072593578779, 0.8271396368504090],
            [0.12705837390565175, 4.095760999428688, 6.3629043590477306, -0.2647332620414719, 0.9803190324362230],
            [3.8792246987611345, 0.4628187934970428, 5.275389020121817, -0.841083084046378, 0.8026827432492923],
            [4.329206786790409, 3.154160821455034, 5.656451848922032, -0.8902551507311377, 0.2058970708329953],
            [1.6238133764067448, 1.6933982779310606, 4.017413723776221, -0.35069597692609966, 0.8071004579985515],
            [4.447342438624, 2.413853133293552, 5.246328053469754, -0.2795499000103847, 0.6012831347007654],
            [3.8278467382227976, 2.8502582680905317, 6.2552646881092, -0.48583213941747266, 0.4889642634225527],
            [2.661390863971771, 2.1949509899568933, 3.224938680832009, -0.8485820586262938, 0.3237202718622643],
            [0.25400300986499785, 3.2184110151925243, 4.504300967883341, -0.47194355030517937, 0.9295608388970047],
            [4.547075722237856, 1.3215319228294873, 6.07303302982693, -0.23978192976953425, 0.8053566031934476],
            [1.2211110109089502, 0.47720155816108567, 2.4454896431933704, -0.7984519899812358, 0.8593804849258645],
            [4.655518496478608, 4.059789859865643, 6.739027887754667, -0.13082704522354535, 0.7067344350757392],
            [4.037993176805661, 1.0141932885415756, 6.769390673030605, -0.4430182925992883, 0.7914871795388971],
        ];
    }

    /**
     * @test hypergeometric throws an OutOfBoundsException if n is greater than 1
     */
    public function testHypergeometricExceptionNGreaterThanOne()
    {
        // Then
        $this->expectException(Exception\OutOfBoundsException::class);

        // When
        Special::hypergeometric(1, 1, 1, 1);
    }

    /**
     * @test generalizedHypergeometric throws a BadParameterException if the parameter count is wrong
     */
    public function testGeneralizedHypergeometricExceptionParameterCount()
    {
        // Then
        $this->expectException(Exception\BadParameterException::class);

        // When
        Special::generalizedHypergeometric(2, 1, ...[6.464756838, 0.509199496, 0.241379523]);
    }
}
